package com.ibm.st.talent.update.profile.status;

/*
 * Licensed Materials - Property of IBM
 *
 * L-KBIM-82KJL8
 *
 * (C) Copyright IBM Corp. 2006, 2010. All rights reserved.
 *
 * US Government Users Restricted Rights- Use, duplication or
 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 */

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.progress.UIJob;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import com.ibm.collaboration.realtime.buddylist.BuddyList;
import com.ibm.collaboration.realtime.buddylist.BuddyListServiceUtil;
import com.ibm.collaboration.realtime.im.community.Community;
import com.ibm.collaboration.realtime.im.community.CommunityService;
import com.ibm.collaboration.realtime.imhub.actions.BuddyListDelegate;
import com.ibm.collaboration.realtime.people.Person;
import com.ibm.collaboration.realtime.servicehub.ServiceException;
import com.ibm.collaboration.realtime.servicehub.ServiceHub;

/**
 * Delegate action contributed to the main window (buddy list).
 */

public class ProfileUpdateDelegate implements BuddyListDelegate {

	private String userid = getCurrentUserId();
	private String password = "";
	
	private HashMap<String, String> buddiesStatusMap;	

	public void run(ISelection selection) {
		
		runStatusJobs();

		Shell shell = new Shell(Display.getCurrent());		
		ProfileUpdateDialog dialog = new ProfileUpdateDialog(shell);

		dialog.setUserid(userid);
		dialog.setPassword(password);
		if(dialog.open() == Window.OK){
			password = dialog.getPassword();
		}
		
	}

	private void runStatusJobs() {
		Job checkStatusJob = new Job("checking status...") {
			@Override
			protected IStatus run(IProgressMonitor arg0) {
				try {
					buddiesStatusMap = getBuddiesStatus();

				} catch (HttpException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return Status.OK_STATUS;

			};
		};

		Job updateStatusJob = new UIJob("updating status...") {
			public IStatus runInUIThread(IProgressMonitor monitor) {
				try {
					updateBuddiesStatus();
				} catch (HttpException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				return Status.OK_STATUS;
			}
		};
		
		ISchedulingRule Schedule_RULE = new ISchedulingRule() {
			public boolean contains(ISchedulingRule rule) {
				return this.equals(rule);
			}

			public boolean isConflicting(ISchedulingRule rule) {
				return this.equals(rule);
			}
		};

		checkStatusJob.setRule(Schedule_RULE);
		updateStatusJob.setRule(Schedule_RULE);
		
		checkStatusJob.schedule();
		updateStatusJob.schedule();
	}
	
	private HashMap<String, String> getBuddiesStatus() throws HttpException, IOException{
		BuddyList list = BuddyListServiceUtil.getBuddyListService().getBuddyList();
		Person[] persons = list.getAllPersons(true);
		HashMap<String, String> map = new HashMap<String, String>();
		
		for(Person person : persons){
			String userId = person.getContactId();			
			if(userId.equalsIgnoreCase(getCurrentUserId()))
				continue;
			
			String status = this.getBuddyStatus(userId);			
//			System.out.println(userId+", "+status);
			
			map.put(userId, status);			
		}		
		return map;
	}
	
	private void updateBuddiesStatus() throws HttpException, IOException{
		for(String userId : this.buddiesStatusMap.keySet()){
			String status = this.buddiesStatusMap.get(userId);
			if(status == null) continue;
			this.updateBuddyDisplayStatus(userId, status);
		}
	}
	
	private String getBuddyStatus(String userId) throws IOException, HttpException {
		InputStream responseStream = getStatusFeed(userId);
		String status = parseStatusFeed(responseStream);
		return status;
	}

	private InputStream getStatusFeed(String userId) throws IOException, HttpException {
		
		String user = userId.replace("@", "%40");
		String url = "https://w3.ibm.com/connections/profiles/atom/mv/theboard/entry/status.do?email="
				+ user;
		
		HttpClient client = new HttpClient();
		
		GetMethod method = new GetMethod(url);		
		method.addRequestHeader("Content-Type", "application/atom+xml; charset=UTF-8");		
		
		int statusCode = client.executeMethod(method);
		if (statusCode == HttpStatus.SC_OK) {
			InputStream responseStream = method.getResponseBodyAsStream();
			return responseStream;
			
		}if (statusCode == HttpStatus.SC_NO_CONTENT){
			return null;
			
		}else{
		  System.err.println("Method failed: " + method.getStatusLine());
		  return null;
		}
	}
	
	private void updateBuddyDisplayStatus(String userId, String newStatus) {
		
		BuddyList list = BuddyListServiceUtil.getBuddyListService().getBuddyList();
		Person[] persons = list.getAllPersons(true);
		
		for(Person person : persons){
			if(userId.equalsIgnoreCase(person.getContactId())){
				String displayName = person.getDisplayName();
				int indexOfStatus = displayName.indexOf(" - [");
				String trueName = indexOfStatus > 0 ? displayName.substring(0, indexOfStatus) 
						: displayName;
				person.setDisplayName(trueName + " - ["+ newStatus +"]");
			}
		}
	}

	private String parseStatusFeed(InputStream responseStream) throws IOException {
		
		if(responseStream == null) return null;
		
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();			
			Document doc = builder.parse(responseStream);
			
			XPathFactory xFactory = XPathFactory.newInstance();  
			XPath xpath = xFactory.newXPath();  
			String status = xpath.evaluate("/entry/content", doc);  
			
			return status;
			
		} catch (XPathExpressionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			responseStream.close();
		}
		
		return null;
	}

	private String getCurrentUserId() {
		
		try {
			CommunityService communityMgr = (CommunityService) ServiceHub.getService(
					CommunityService.SERVICE_TYPE);
			Community community = communityMgr.getDefaultCommunity();
			
			if (null != community) {
				return community.getUserId();
			}
			
		} catch (ServiceException e) {
			e.printStackTrace();
		}
		
		return null;

	}
}
